package game.breeze.gameserver.controller;

import game.breeze.astar.AStar;
import game.breeze.astar.AStarNode;
import game.breeze.constants.MapItemType;
import game.breeze.message.AppMessage;
import game.breeze.message.SceneMessageCode;
import game.breeze.resource.GameMapDef;
import game.breeze.resource.MapItemDef;
import game.breeze.resource.MapMonsterDef;
import game.breeze.resource.manager.GameResourceManager;

import java.util.ArrayList;
import java.util.List;

public class GameMapController extends ContainerController {
	private GameMapDef gameMap;
	private AStar astar;
	private List<MonsterController> monsters;
	int cellSize;
	float rebornTime = .0f;
	float runtime = .0f;

	public GameMapController(GameMapDef def) {
		this.gameMap = def;
		cellSize = def.getCellSize();
		astar = new AStar(def.getGrid());
		monsters = new ArrayList<MonsterController>();
		for (MapItemDef monster : gameMap.items) {
			if (monster.getMapItemType() != MapItemType.monster) {
				continue;
			}
			MapMonsterDef mmf = (MapMonsterDef) monster;
			MonsterController m = new MonsterController(this, GameResourceManager.getInstance().getMonsterResourceManager().findMonster(mmf.getMonster()));
			m.setId(monster.getId());
			m.setPositions(mmf.getMovePoints());
			monsters.add(m);
		}
	}

	/**
	 * 刷新地图
	 */
	@Override
	public void update(float delta) {
		runtime += delta;
		// 怪物是否需要复活
		boolean reborn = runtime - rebornTime >= gameMap.getMonsterReborn();
		// 如果需要复活,重置复活时间
		rebornTime = runtime;

		for (PlayerController controller : controllers.values()) {
			controller.update(delta);
		}
		// 更新怪物状态
		for (MonsterController monster : monsters) {
			// 死亡的怪物需要复活
			if (reborn && monster.isDead()) {
				// 复活
				monster.reborn();
				// 保持原始状态
				continue;
			}
			// 可以移动(到达移动时间,并且有移动路径)
			if (monster.canMove(runtime)) {
				// 移动
				monster.walk();
			}
		}

		synMonster();
	}

	/**
	 * 寻找最佳路径
	 * 
	 * @param x
	 *            起点
	 * @param y
	 *            起点
	 * @param dx
	 *            终点
	 * @param dy
	 *            终点
	 * @return 路径节点
	 */
	public List<AStarNode> findPath(int x, int y, int dx, int dy) {
		int col = (int) (x / cellSize);
		int row = (int) (y / cellSize);
		int dcol = (int) (dx / cellSize);
		int drow = (int) (dy / cellSize);
		return astar.astar(row, col, drow, dcol);// path.find(x, y,
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * game.breeze.gameserver.controller.ContainerController#onControllerAdded
	 * (game.breeze.gameserver.controller.PlayerController)
	 */
	@Override
	public void onControllerAdded(PlayerController controller) {
		// 玩家进入地图消息
		AppMessage addedMessage = AppMessage.createMessage(AppMessage.MSG_SCENE);
		addedMessage.getBuffer().writeInt(SceneMessageCode.MSG_SCENE_PLAYER_ADDED);
		controller.getPlayer().writeTo(addedMessage.getBuffer());
		// 通知各玩家,新玩家进入此地图
		for (PlayerController heroController : controllers.values()) {
			heroController.sendMessage(addedMessage);
		}
	}

	/**
	 * 同步玩家在此地图的数据.
	 * 
	 * @param controller
	 *            玩家
	 */
	public void synPlayerMove(PlayerController controller) {
		// 玩家进入地图消息
		AppMessage moveMessage = AppMessage.createMessage(AppMessage.MSG_SCENE);
		moveMessage.getBuffer().writeInt(SceneMessageCode.MSG_SCENE_PLAYER_MOVE);
		controller.getPlayer().writeTo(moveMessage.getBuffer());
		// 通知各玩家,新玩家进入此地图
		for (PlayerController heroController : controllers.values()) {
			// 忽略自己
			if (controller == heroController) {
				continue;
			}
			heroController.sendMessage(moveMessage);
		}
	}

	/**
	 * 同步地图怪物数据
	 */
	public void synMonster() {
		AppMessage monsterMessage = AppMessage.createMessage(AppMessage.MSG_SCENE);
		monsterMessage.getBuffer().writeInt(SceneMessageCode.MSG_SCENE_MONSTER);
		monsterMessage.getBuffer().writeInt(monsters.size());
		for (MonsterController m : monsters) {
			m.writeTo(monsterMessage.getBuffer());
		}
		// 通知各玩家,怪物数据发生变化
		for (PlayerController heroController : controllers.values()) {
			heroController.sendMessage(monsterMessage);
		}
	}
}
